#pragma once
#include "base/net/callback.h"
#include "net_define.h"
#include "module.h"
#include "session.h"
#include "base/core/object_pool.h"
#include "base/core/raw_allocator.h"
#include <map>

using std::map;

typedef ObjectPool<Session> SessionPool;

class Handle 
{
public:
	Handle() {}
	virtual ~Handle() {}

	virtual bool Readable(EventData* data) = 0;
	virtual bool Writable(EventData* data) = 0;
	virtual int  Error(EventData* data) = 0;
};

class HandleLink : public Handle 
{
protected:
	uint64_t      m_tick_ms;
	ICallback*    m_callback;
	Module*       m_module;
	DoubleList*   m_fixe_timeout;
	DoubleList*   m_connect_list;
	RawAllocator* m_buffPool;
	SessionPool*  m_sessionPool;
	Handle*       m_handleLinked;

public:
	HandleLink();
	virtual ~HandleLink();

	virtual bool Readable(EventData* data);
	virtual bool Writable(EventData* data);
	virtual int  Error(EventData* data);

public:
	bool Init(RawAllocator* buff_pool,
			SessionPool*  session_pool,
			Module*       module,
			DoubleList*   fixe_timeout,
			DoubleList*   connect_list,
			Handle*       handle_linked,
			ICallback*    callback);
	bool UpdateTick(uint64_t tick_ms);
	bool SetCallback(ICallback* callback);

protected:  
	bool AddAcceptSession(SOCKET sock, uint16_t local_port, EventDataEx* data);
	bool AddConnectSession(SOCKET sock, uint16_t local_port, EventDataEx* data);
};

class HandleLinked : public Handle 
{
protected:
	uint64_t      m_tick_ms;
	ICallback*    m_callback;
	Module*       m_module;
	DoubleList*   m_fixe_timeout;
	DoubleList*   m_free_timeout;
	DoubleList*   m_connect_list;
	SessionPool*  m_sessionPool;

public:
	HandleLinked();
	virtual ~HandleLinked();

	virtual bool Readable(EventData* data);
	virtual bool Writable(EventData* data);
	virtual int  Error(EventData* data);

public:
	bool Init(SessionPool*  session_pool,
			Module*       module,
			DoubleList*   fixe_timeout,
			DoubleList*   free_timeout,
			DoubleList*   connect_list, 
			ICallback*    callback);
	bool UpdateTick(uint64_t tick_ms);
	bool HandlePackage(Session* session);
	void Timeout(Session* session);
	bool SetCallback(ICallback* callback);

protected:
	void ErrorSession(Session* session, CloseFlag flag);
};
